/**
Defines thread functions to handle echo and daytime clients.
*/
#include "globals.h"

/**
The thread function for an echo client.

@param arg supplies the arguments for the thread function. This is a pointer to
           the socket file descriptor in this case.

@return NULL.
*/
void* 
echo_thread_func(
    void* arg
    )
{
    int connfd;

    connfd = *((int *) arg);
    free(arg);

    Pthread_detach(pthread_self());

    str_echo_ext(connfd);

    Close(connfd);
    
    return (NULL);
}

/**
The thread function for a daytime client.

@param arg supplies the arguments for the thread function. This is a pointer to
           the socket file descriptor in this case.

@return NULL.
*/
void* 
time_thread_func(
    void* arg
    )
{
    int connfd;
    time_t ticks;
    char buff[MAXLINE];
    int n;
    int maxfd;
    fd_set rset;
    struct timeval timeout;

    connfd = *((int *) arg);
    free(arg);

    Pthread_detach(pthread_self());
    
    //
    // Forever write daytime data to the socket every 5 seconds.
    //

    while (TRUE)
    {
        FD_SET(connfd, &rset);
        maxfd = connfd + 1;

        ticks = time(NULL);
        snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
        
        if (write(connfd, buff, strlen(buff)) < 0)
        {
            //
            // Terminate with an error message to handle EPIPE.
            //

            if (errno == EPIPE)
            {
                log_server_error(DIAG_TIME_SRV_TERM_ERR, EPIPE);
                Close(connfd);
                return NULL;
            }
            else
            {
                err_sys("write error.");
            }
        }

        bzero(buff, MAXLINE);
        
        //
        // Set the time out value to 5 seconds.
        //

        timeout.tv_sec = 5;
        timeout.tv_usec = 0;

        Select(maxfd, &rset, NULL, NULL, &timeout);

        //
        // To poll if the client has sent the FIN.
        //

        if (FD_ISSET(connfd, &rset))
        {
            n = ts_readline(connfd, buff, MAXLINE);

            //
            // Number of data bytes sent would be 0 when FIN has been received.
            // This happens when the client terminates.
            //

            if (n == 0)
            {
                log_server(DIAG_TIME_SRV_TERM);
                Close(connfd);
                break;
            }
            else
            {
                err_sys("time server: read error.");
            }
        }
    }
    
    return (NULL);
}

